HDU 5651 xiaoxin juju needs help(组合数学)

题意:

$N\le 2\times 10^3的字符串,字符集大小为26$
$现在重排它,问有多少个不同的回文串$

分析:

$这个很显然了,num_{字符出现奇数个数}>1肯定GG$
$没出现奇数字符直接搞就好了,出现了就取出1个放在中间,剩下的都是偶数个数了$
$ans=\frac{ {\frac{n}{2}}!} {c_1 !\cdot c_2!\cdots c_m!},很简单的组合计数啦$
$就是要求个逆元$

代码:

//
//  Created by TaoSama on 2016-04-07
//  Copyright (c) 2016 TaoSama. All rights reserved.
//
#pragma comment(linker, "/STACK:102400000,102400000")
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <string>
#include <set>
#include <vector>

using namespace std;
#define pr(x) cout << #x << " = " << x << "  "
#define prln(x) cout << #x << " = " << x << endl
const int N = 1e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7;

char s[N];
int f[N], inv[N], finv[N];

int main() {
#ifdef LOCAL
    freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin);
//  freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout);
#endif
    ios_base::sync_with_stdio(0);

    f[0] = inv[0] = finv[0] = 1;
    f[1] = inv[1] = finv[1] = 1;
    for(int i = 2; i <= 1000; ++i) {
        f[i] = 1LL * i * f[i - 1] % MOD;
        inv[i] = 1LL * (MOD - MOD / i) * inv[MOD % i] % MOD;
        finv[i] = 1LL * inv[i] * finv[i - 1] % MOD;
    }

    int t; scanf("%d", &t);
    while(t--) {
        scanf("%s", s);
        int n = strlen(s);

        vector<int> c(26, 0);
        for(int i = 0; i < n; ++i) c[s[i] - 'a']++;

        int odd = 0;
        for(int i = 0; i < 26; ++i) odd += c[i] & 1;
        if(odd > 1) {puts("0"); continue;}

        int ans = f[n / 2];
        for(int i = 0; i < 26; ++i)
            ans = 1LL * ans * finv[c[i] / 2] % MOD;
        printf("%d\n", ans);
    }
    return 0;
}